#include "calculator.h"
#include "ui_calculator.h"


Calculator::Calculator(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Calculator)
    , num(0), operation('\0'), isNewOperation(true), isFirstElement(true), hasDecimalPoint(false), decimalPlaces(0.1)
    , decimalCount(0), EqualBtnClicked(false)
{
    ui->setupUi(this);

    // 加载样式表
    loadStyleSheetFile(":/qss/ToolButton.qss");
    // 初始化槽函数连接
    initConnections();
}

Calculator::~Calculator()
{
    delete ui;
}

void Calculator::loadStyleSheetFile(const QString &styleSheetFile)
{
    // 设置按钮属性
    ui->btnEqual->setObjectName("equal");
    ui->btnAdd->setObjectName("operator");
    ui->btnSub->setObjectName("operator");
    ui->btnMul->setObjectName("operator");
    ui->btnDiv->setObjectName("operator");

    ui->btnC->setObjectName("special");
    ui->btnCE->setObjectName("special");
    ui->btnPer->setObjectName("special");
    ui->btnFraction->setObjectName("special");
    ui->btnSquare->setObjectName("special");
    ui->btnSqrt->setObjectName("special");

    // 加载样式表
    QFile file(styleSheetFile);
    if (file.open(QFile::ReadOnly)) {
        QString styleSheet = QString::fromUtf8(file.readAll()); // 使用 fromUtf8 处理编码
        this->setStyleSheet(styleSheet);
    } else {
        QMessageBox::information(this, "Error", QString("Failed to open file: %1").arg(styleSheetFile));
    }
}

void Calculator::btnNumClicked(double x)
{
    if(EqualBtnClicked) {
        sentence = "";
        num = '\0';
    }

    // 处理数字输入
    if (isFirstElement) {
        num = x;
        isFirstElement = false;
        ui->displayLabel->setText(QString::number(num, 'f', decimalCount));
    } else {
        if (hasDecimalPoint) {
           // 处理小数部分
           num += x * decimalPlaces;
           decimalPlaces /= 10; // 减少小数点后面的位数
           decimalCount++;
           qDebug() << "decimalConut: " << decimalCount;
           ui->displayLabel->setText(QString::number(num, 'f', decimalCount));
       } else {
           // 处理整数部分
           num = num * 10 + static_cast<int>(x);
           ui->displayLabel->setText(QString::number(num, 'f', decimalCount));
       }
    }
}

void Calculator::btnSpotClicked()
{
    if(isFirstElement || hasDecimalPoint) {
        return;
    }

    hasDecimalPoint = true;
}

void Calculator::btnBackClicked()
{
    if(EqualBtnClicked) {
        sentence = "";
        num = '\0';
    }

    QString currentText = ui->displayLabel->text(); // 获取当前显示的文本
    if (currentText.isEmpty()) {
        return; // 如果没有文本，直接返回
    }

    // 移除最后一个字符
    currentText.chop(1); // 或者使用 remove() 方法：currentText.remove(currentText.length() - 1, 1);

    // 如果移除后的文本为空，重置显示为 0
    if (currentText.isEmpty()) {
        currentText = "0";
    }

    // 更新显示标签
    ui->displayLabel->setText(currentText);

    // 更新 num 变量
    bool ok;
    num = currentText.toDouble(&ok);
    if (!ok) {
        num = 0; // 如果转换失败，则将 num 设置为 0
    }
}

void Calculator::btnOperatorClicked(char op)
{
    if(EqualBtnClicked) {
        sentence = "";
        num = '\0';
    }

    // 如果上一次操作后有数字，则将其加入 sentence
    if (!isFirstElement) {
        if ((!sentence.isEmpty() && !sentence.back().isDigit()) || sentence.isEmpty())
            sentence += QString::number(num, 'f', decimalCount);

        qDebug() << "num: " << num;
        num = 0;  // 重置 num 以便输入新的数字
        isFirstElement = true;  // 标记新的数字输入开始
    }

    // 检查 sentence 是否以运算符结尾
    if (!sentence.isEmpty() && (sentence.endsWith('+') || sentence.endsWith('-') || sentence.endsWith('*') || sentence.endsWith('/'))) {
        // 如果最后一位是运算符，替换运算符
        sentence.chop(1);  // 删除最后一个运算符
    }

    // 追加新的运算符
    sentence += op;

    // 更新显示
    ui->outputLabel->setText(sentence);
    ui->displayLabel->setText("");
    size_t tmp = decimalCount;
    initMembers();
    decimalCount = tmp;
}

void Calculator::btnCClicked()
{
    // 清空全部内容
    initMembers();
    sentence = "";
    // ui-> displayLabel->setText("displayLabel");
    // ui->outputLabel->setText("outputLabel");
    ui-> displayLabel->setText("");
    ui->outputLabel->setText("");
}

void Calculator::btnCEClicked()
{
    initMembers();
    ui->displayLabel->setText("");
}

void Calculator::btnSquareClicked()
{
    num *= num;
    ui->displayLabel->setText(QString::number(num, 'f', decimalCount + 6));
}

void Calculator::btnSqrtClicked()
{
    if (num >= 0) { // 防止负数开根号的错误
        num = sqrt(num); // 计算平方根
        ui->displayLabel->setText(QString::number(num, 'f', decimalCount + 6)); // 显示6位小数
    } else {
        ui->displayLabel->setText("Error: 负数不能开根号"); // 处理负数开根号的情况
    }
}

void Calculator::btnFractionClicked()
{
    if (num != 0) { // 防止除以0的错误
        num = 1.0 / num;
        ui->displayLabel->setText(QString::number(num, 'f', decimalCount + 6)); // 显示6位小数
    } else {
        ui->displayLabel->setText("Error: 除数不能为0"); // 处理除以0的情况
    }
}

void Calculator::btnPerClicked()
{
    num = num / 100.0; // 将当前值转换为百分比
    ui->displayLabel->setText(QString::number(num, 'f', decimalCount + 6)); // 显示6位小数
}

void Calculator::btnReverseClicked()
{
    num = -num;
    ui->displayLabel->setText(QString::number(num, 'f', decimalCount)); // 更新显示，6位小数
}

bool Calculator::btnEqualClicked() {
    if(isPureNumber(sentence)) {
        qDebug() << "1sentence: " << sentence;
        ui->outputLabel->setText(QString::number(num, 'f', decimalCount));
        sentence = QString::number(num, 'f', decimalCount);
        return true;
    }
    qDebug() << "2sentence: " << sentence;
    // 将当前数字（num）转换为字符串，并添加到当前计算表达式（sentence）中
    sentence += QString::number(num, 'f', decimalCount);
    qDebug() << "3sentence: " << sentence;
    QString str = sentence; // 将表达式字符串复制到局部变量
    QStack<double> numbers; // 用于存储操作数的栈
    QStack<QChar> operators; // 用于存储操作符的栈

    if(!sentence.begin()->isDigit()) {
        ui->outputLabel->setText("Error: There are no numbers before the operator."); // 显示结果（保留两位小数）
        ui->displayLabel->setText("");

        initMembers();
        sentence = "";
        return false;
    }

    // 定义操作符的优先级
    QMap<QChar, int> precedence = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}};

    str = str.trimmed(); // 去除前后的空白字符
    int length = str.length(); // 获取表达式的长度
    for (int i = 0; i < length; ++i) {
        QChar ch = str[i]; // 当前字符

        // 处理数字或小数点
        if (ch.isDigit() || (ch == '.' && (i > 0 && str[i - 1].isDigit()))) {
            QString numberStr;
            while (i < length && (str[i].isDigit() || str[i] == '.')) {
                numberStr += str[i++]; // 读取完整的数字（包括小数点）
            }
            --i; // 回退一个字符，因为循环结束时 i 已经多加了一次
            numbers.push(numberStr.toDouble()); // 将数字转换为 double 并压入操作数栈
        }
        // 处理负号（负数）
        else if (ch == '-' && (i == 0 || (i > 0 && str[i - 1] == '('))) {
            QString numberStr;
            numberStr += ch; // 负号
            while (i + 1 < length && (str[i + 1].isDigit() || str[i + 1] == '.')) {
                numberStr += str[++i]; // 读取负数后的数字
            }
            numbers.push(numberStr.toDouble()); // 将负数转换为 double 并压入操作数栈
        }
        // 处理操作符（+ - * /）
        else if (precedence.contains(ch)) {
            // 处理当前操作符前已有的操作符（具有相同或更高优先级的）
            while (!operators.isEmpty() && precedence[operators.top()] >= precedence[ch]) {
                double right = numbers.pop(); // 从操作数栈弹出右操作数
                double left = numbers.pop(); // 从操作数栈弹出左操作数
                QChar op = operators.pop(); // 从操作符栈弹出操作符

                double result;
                if (op == '+') result = left + right; // 计算加法
                else if (op == '-') result = left - right; // 计算减法
                else if (op == '*') result = left * right; // 计算乘法
                else if (op == '/') {
                    if (right == 0) {  // 处理除以零的情况
                        ui->outputLabel->setText("Error: Division by zero");
                        return false;
                    }
                    result = left / right; // 计算除法
                }

                numbers.push(result); // 将结果压入操作数栈
            }
            operators.push(ch); // 将当前操作符压入操作符栈
        }
//        // 处理左括号
//        else if (ch == '(') {
//            operators.push(ch); // 将左括号压入操作符栈
//        }
//        // 处理右括号
//        else if (ch == ')') {
//            // 处理括号内的表达式
//            while (!operators.isEmpty() && operators.top() != '(') {
//                double right = numbers.pop(); // 从操作数栈弹出右操作数
//                double left = numbers.pop(); // 从操作数栈弹出左操作数
//                QChar op = operators.pop(); // 从操作符栈弹出操作符

//                double result;
//                if (op == '+') result = left + right; // 计算加法
//                else if (op == '-') result = left - right; // 计算减法
//                else if (op == '*') result = left * right; // 计算乘法
//                else if (op == '/') {
//                    if (right == 0) {  // 处理除以零的情况
//                        ui->outputLabel->setText("Error: Division by zero");
//                        return false;
//                    }
//                    result = left / right; // 计算除法
//                }

//                numbers.push(result); // 将结果压入操作数栈
//            }
//            operators.pop(); // 弹出左括号
//        }
    }

    // 处理剩余的操作符
    while (!operators.isEmpty()) {
        double right = numbers.pop(); // 从操作数栈弹出右操作数
        double left = numbers.pop(); // 从操作数栈弹出左操作数
        QChar op = operators.pop(); // 从操作符栈弹出操作符

        double result;
        if (op == '+') result = left + right; // 计算加法
        else if (op == '-') result = left - right; // 计算减法
        else if (op == '*') result = left * right; // 计算乘法
        else if (op == '/') {
            if (right == 0) {  // 处理除以零的情况
                ui->outputLabel->setText("Error: Division by zero");
                return false;
            }
            result = left / right; // 计算除法
        }

        numbers.push(result); // 将结果压入操作数栈
    }

    EqualBtnClicked = true;
    // 确保栈中仅剩一个操作数，即计算结果
    if (numbers.size() == 1) {
        double result = numbers.pop(); // 获取计算结果
        qDebug() << "ret: " << result;
        ui->outputLabel->setText(QString::number(result, 'f', decimalCount)); // 显示结果（保留两位小数）
        ui->displayLabel->setText("");
        sentence = QString::number(result, 'f', decimalCount);

        num = result;
        operation = '\0';
        // isNewOperation = true;
        isFirstElement = true;
        hasDecimalPoint = false;
        decimalPlaces = 0.1;
        decimalCount = 0;
        EqualBtnClicked = false;

        return true;
    } else {
        ui->outputLabel->setText("Error"); // 显示错误信息
        return false;
    }
}

void Calculator::initConnections()
{
    // 初始化数字按钮
    for (int i = 0; i <= 9; ++i)
    {
        connect(findChild<QToolButton*>(QString("btn%1").arg(i)), &QToolButton::clicked, [this, i]() { btnNumClicked(i); });
    }

    // 初始化运算符
    connect(ui->btnAdd, &QToolButton::clicked, [this]() { btnOperatorClicked('+'); });
    connect(ui->btnSub, &QToolButton::clicked, [this]() { btnOperatorClicked('-'); });
    connect(ui->btnMul, &QToolButton::clicked, [this]() { btnOperatorClicked('*'); });
    connect(ui->btnDiv, &QToolButton::clicked, [this]() { btnOperatorClicked('/'); });

    // 绑定 等于按钮
    connect(ui->btnEqual, &QToolButton::clicked, [this]() { btnEqualClicked(); });
    // 绑定其他功能按钮
    connect(ui->btnC, &QToolButton::clicked, [this]() { btnCClicked(); });
    connect(ui->btnCE, &QToolButton::clicked, [this]() { btnCEClicked(); });

    connect(ui->btnBack, &QToolButton::clicked, [this]() { btnBackClicked(); });
    connect(ui->btnSquare, &QToolButton::clicked, [this]() { btnSquareClicked(); });
    connect(ui->btnFraction, &QToolButton::clicked, [this]() { btnFractionClicked(); });
    connect(ui->btnSqrt, &QToolButton::clicked, [this]() { btnSqrtClicked(); });
    connect(ui->btnPer, &QToolButton::clicked, [this]() { btnPerClicked(); });
    connect(ui->btnSpot, &QToolButton::clicked, [this]() { btnSpotClicked(); });
    connect(ui->btnReverse, &QToolButton::clicked, [this]() { btnReverseClicked(); });

}

void Calculator::initMembers()
{
    num = 0;
    operation = '\0';
    isNewOperation = true;
    isFirstElement = true;
    hasDecimalPoint = false;
    decimalPlaces = 0.1;
    decimalCount = 0;
    EqualBtnClicked = false;
}

bool Calculator::isPureNumber(const QString &sen) {
    // 移除空格
    QString trimmedSen = sen.trimmed();

    // 允许小数点
    bool hasDecimalPoint = trimmedSen.contains('.');

    // 使用正则表达式检查是否为纯数字或小数
    QRegularExpression regex(hasDecimalPoint ? "^[-]?\\d*\\.\\d+$" : "^[-]?\\d+$");
    QRegularExpressionMatch match = regex.match(trimmedSen);

    return match.hasMatch();
}
